#ifndef SCENE_H
#define SCENE_H

#include <vector>
#include <map>
#include <GL/gl.h>

#include "models.h"

#define SELECT_BUFFER_LENGTH 64

class Viewport{
    public:
        int left;
        int top;
        int width;
        int height;
        
        Viewport();
        Viewport(int _left, int _top, int _width, int _height);
        ~Viewport();

        void setViewport(int _left, int _top, int _width, int _height);
};

class Window{
    public:
        float left;
        float right;
        float bottom;
        float top;
        
        Window();
        Window(float _left, float _right, float _bottom, float _top);
        ~Window();

        void setWindow(float _left, float _right, float _bottom, float _top);
};


class Selected{
    public:
        int count;
        int zmin;
        int zmax;
        int id;

        Selected();
        ~Selected();

        void show();
};

class Scene{
    protected:
        Viewport viewport;
        Window window;

        float rotate_x;
        float rotate_y;
        float rotate_z;

        float translate_x;
        float translate_y;
        float translate_z;

        float scale_x;
        float scale_y;
        float scale_z;
        
        map<int, Object> objects;
        
        Ground ground;
        Plane plane;
        bool showPlane;
        
        vector<Sphere> spheres;
        vector< Segment > segments;
        
        vector< vector<Point> > polygons;
        vector< pair<Point, Point> > lines;
        
        
    public:
    
        void setViewport(int _left, int _top, int _width, int _height);
        Viewport &getViewport();
        
        void setWindow(float _left, float _right, float _bottom, float _top);
        Window &getWindow();
    
        void setRotateX(float rx);
        float getRotateX();
        void setRotateY(float ry);
        float getRotateY();
        void setRotateZ(float rz);
        float getRotateZ();  
        
        void setTranslateX(float tx);
        float getTranslateX();
        void setTranslateY(float ty);
        float getTranslateY();
        void setTranslateZ(float tz);
        float getTranslateZ();
        
        void setScaleX(float sx);
        float setScaleX();
        void setScaleY(float sy);
        float setScaleY();
        void setScaleZ(float sz);
        float setScaleZ();                   

        void rotate(float angle, Point direction);
        
        Point getScenePoint(Cursor &cursor);
        vector<Selected> parseSelectedBuffer(GLuint selectBuff[SELECT_BUFFER_LENGTH]);
        vector<Selected> selectElements(int xPos, int yPos);
        virtual int ProcessPick(GLuint selectBuff[SELECT_BUFFER_LENGTH]){}

        void setPlane(Plane _plane);
        void enablePlane();
        void disablePlane();
        virtual void updateEnviroment(){}
        void drawEnviroment();

        void addObject(Object object, int objId);        
        void setObjects(map<int, Object> objs);
        map<int, Object>& getObjects();
        void drawObjects();

        void addSphere(Sphere s);
        void drawSpheres();

        void addSegment(Segment s);
        void removeSegment(Segment s){
            int size = segments.size();
            for(int i = 0; i < size; i++){
                if (segments[i] == s){
                    segments.erase(segments.begin() + i);
                }
            }
        }
        
        vector<Segment>& getSegments(){return segments;}
        void drawSegments();
        void clearSegments(){segments.clear();}


        void addPolygon(vector<Point> polygon){
            this->polygons.push_back(polygon);
        }
        
        void drawPolygons(){
            for (int i = 0; i < polygons.size(); i++){
                Polygon poly(polygons[i]);
                poly.draw(0.0, 1.0, 0.0);
            }
        }
        
        void addLine(Point origin, Point destination){
            pair<Point, Point> line;
            line.first = origin;
            line.second = destination;
            this->lines.push_back(line);
        }
        
        void drawLines(){
            glColor3f(0.0, 0.0, 1.0);
            for (int i = 0; i < lines.size(); i++){
                glBegin(GL_LINE_STRIP);
                glVertex3f( lines[i].first.getX(),
                            lines[i].first.getY(),
                            lines[i].first.getZ() );
                            
                glVertex3f( lines[i].second.getX(),
                            lines[i].second.getY(),
                            lines[i].second.getZ() );  
                glEnd();   
            }
            
        }   
        
        virtual void setUp(){}
};

#endif /* SCENE_H */
